package me.illtamer.rpc.transport.socket.server;

import lombok.extern.slf4j.Slf4j;
import me.illtamer.rpc.factory.ThreadPoolFactory;
import me.illtamer.rpc.handler.RequestHandler;
import me.illtamer.rpc.hook.ShutdownHook;
import me.illtamer.rpc.provider.ServiceProviderImpl;
import me.illtamer.rpc.register.NacosServiceRegistry;
import me.illtamer.rpc.transport.AbstractRpcServer;
import me.illtamer.serializer.CommonSerializer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;

/**
 * Socket 方式进行远程调用连接的服务端实现
 * */
@Slf4j
public class SocketServer extends AbstractRpcServer {

    private final RequestHandler requestHandler = new RequestHandler();
    private final ExecutorService threadPool;
    private final CommonSerializer serializer;


    public SocketServer(String host, int port) {
        this(host, port, DEFAULT_SERIALIZER);
    }
    public SocketServer(String host, int port, int serializerCode) {
        super.host = host;
        super.port = port;
        super.serviceRegistry = new NacosServiceRegistry();
        super.serviceProvider = new ServiceProviderImpl();
        this.threadPool = ThreadPoolFactory.createDefaultThreadPool("socket-rpc-server");
        this.serializer = CommonSerializer.getByCode(serializerCode);
        scanServices();
    }

    /**
     * RPC 服务端启动
     * */
    @Override
    public void start() {
        try (ServerSocket serverSocket = new ServerSocket()) {
            serverSocket.bind(new InetSocketAddress(host, port));
            log.info("服务器已启动！");
            // 添加钩子，服务端关闭时会注销服务
            ShutdownHook.SHUTDOWN_HOOK.addClearAllHook();
            Socket socket;
            // 阻塞等待连接
            while ((socket = serverSocket.accept()) != null) {
                log.info("客户端连接 - {}:{}", socket.getInetAddress(), socket.getPort()); // socket 的出站端口号
                threadPool.execute(new SocketRequestHandlerThread(socket, requestHandler, serializer));
            }
            threadPool.shutdown();;
        } catch (IOException e) {
            log.error("服务端启动时发生错误：" + e);
        }
    }

}
